package com.gitee.shoes.crawler.core;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONUtil;
import com.gitee.shoes.crawler.bean.*;
import com.gitee.shoes.crawler.exception.ApiRequestException;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.function.Consumer;

/**
 * @author LYH
 */
@Slf4j
public abstract class AbstractApiRequest {

    /**
     * 请求前设置，方便之后设置代理
     */
    @Setter
    protected Consumer<HttpRequest> preRequestConsumer;

    /**
     * 搜索
     *
     * @param keyword   关键字
     * @param page      页码 毒从0开始 识货从1开始
     * @param limit     条数 毒特有 最大为20，大于无效。识货默认20条
     * @param nextKey   下一个key nice特有
     * @param orderMode 排序方式 毒/识货特有
     * @return
     */
    public abstract ApiProductList productList(String keyword, Integer page, Integer limit, String nextKey, OrderMode orderMode);

    /**
     * 商品详情
     *
     * @param mainId
     * @param styleId   识货特有
     * @return
     */
    public abstract ApiProduct productDetail(String mainId, String styleId);

    /**
     * 当前最低售价
     *
     * @param mainId
     * @param styleId         识货特有
     * @param productSizeList 毒特有
     * @return
     */
    public abstract ApiProductBuyNowList productBuyNowList(String mainId, String styleId, List<ApiProductSize> productSizeList);

    /**
     * 最近购买记录
     *
     * @param mainId
     * @param styleId
     * @param limit
     * @param lastId
     * @return
     */
    public abstract ApiProductLastSoldList productLastSoldList(String mainId, String styleId, Integer limit, String lastId);

    protected void fillRequest(HttpRequest request) {

    }

    protected String handlerArticle(String article) {
        if (article == null) {
            return null;
        }
        /**
         * 所有空格换成一个-
         */
        article = StrUtil.trim(article);
        return ReUtil.replaceAll(article, "\\W{1,}", "-");
    }

    private String request(Method method, String url, String requestBody) {
        requestBody = StrUtil.nullToEmpty(requestBody);
        HttpRequest request = HttpUtil.createRequest(method, url).setMaxRedirectCount(3);
        request.header("Host", URLUtil.url(url).getHost());
        request.header("Connection", "keep-alive");
        if (!requestBody.isEmpty()) {
            request.header("Content-Length", StrUtil.toString(requestBody.length()));
        }
        request.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat");
        request.header("content-type", JSONUtil.isJson(requestBody) ? "application/json" : "application/x-www-form-urlencoded");
        request.header("Referer", "https://servicewechat.com/wx67b11ce5112789b5/68/page-frame.html");
        request.header("Accept-Encoding", "gzip, deflate, br");
        request.body(requestBody);
        if (this.preRequestConsumer != null) {
            this.preRequestConsumer.accept(request);
        }
        fillRequest(request);
        log.debug("【请求信息】：{}", request);
        String responseBody = request.execute().body();
        log.debug("【响应报文】：{}", responseBody);
        return responseBody;
    }

    protected <T extends IResp> T request(Method method, String url, String requestBody, TypeReference<T> responseType) {
        String responseBody = request(method, url, requestBody);
        T t = JSONUtil.toBean(responseBody, responseType, false);
        if (!t.isSuccess()) {
            log.error("接口请求失败，{}，{}，{}，{}", method, url, requestBody, responseBody);
            throw new ApiRequestException("接口请求失败");
        }
        return t;
    }

}
